package com.training.utils;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.UUID;

// 添加Thumbnailator导入
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;

import javax.crypto.SecretKey;

@Component
public class FileUploadUtil {

    @Value("${upload.path:./uploads}")
    private String uploadPath;

    /**
     * 上传文件并返回相对路径
     *
     * @param file 要上传的文件
     * @return 文件的相对路径，如果文件为空则返回null
     * @throws IOException 文件操作异常
     */
    public String uploadFile(MultipartFile file) throws IOException {
        return uploadFileToSubdirectory(file, null);
    }

    /**
     * 上传文件到指定子目录并返回相对路径
     *
     * @param file 要上传的文件
     * @param subDirectory 子目录名称，例如 "avatar" 或 "course/1"
     * @return 文件的相对路径，如果文件为空则返回null
     * @throws IOException 文件操作异常
     */
    public String uploadFileToSubdirectory(MultipartFile file, String subDirectory) throws IOException {
        if (file == null || file.isEmpty()) {
            return null;
        }

        // 确保上传目录存在
        String targetPath = uploadPath;
        if (subDirectory != null && !subDirectory.isEmpty()) {
            targetPath = Paths.get(uploadPath, subDirectory).toString();
        }
        
        File uploadDir = new File(targetPath);
        if (!uploadDir.exists()) {
            uploadDir.mkdirs();
        }

        // 生成唯一文件名
        String originalFilename = file.getOriginalFilename();
        String fileExtension = "";
        if (originalFilename != null && originalFilename.contains(".")) {
            fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
        }
        String uniqueFilename = UUID.randomUUID().toString() + fileExtension;

        // 保存文件
        Path filePath = Paths.get(targetPath, uniqueFilename);
        try {
            Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        
        // 验证文件是否真的保存成功
        if (!Files.exists(filePath)) {
            throw new IOException("文件保存失败: " + filePath.toString());
        }

        // 返回相对路径
        if (subDirectory != null && !subDirectory.isEmpty()) {
            return "/uploads/" + subDirectory + "/" + uniqueFilename;
        } else {
            return "/uploads/" + uniqueFilename;
        }
    }
    
    /**
     * 上传并加密音频文件到指定子目录并返回相对路径
     *
     * @param file 要上传的文件
     * @param subDirectory 子目录名称，例如 "avatar" 或 "course/1"
     * @param encryptionKey 加密密钥
     * @return 文件的相对路径，如果文件为空则返回null
     * @throws Exception 文件操作或加密异常
     */
    public String uploadAndEncryptAudioFileToSubdirectory(MultipartFile file, String subDirectory, SecretKey encryptionKey) throws Exception {
        if (file == null || file.isEmpty()) {
            return null;
        }

        // 确保上传目录存在
        String targetPath = uploadPath;
        if (subDirectory != null && !subDirectory.isEmpty()) {
            targetPath = Paths.get(uploadPath, subDirectory).toString();
        }
        
        File uploadDir = new File(targetPath);
        if (!uploadDir.exists()) {
            uploadDir.mkdirs();
        }

        // 生成唯一文件名
        String originalFilename = file.getOriginalFilename();
        String fileExtension = "";
        if (originalFilename != null && originalFilename.contains(".")) {
            fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
        }
        String uniqueFilename = UUID.randomUUID().toString() + fileExtension;

        // 构建临时文件路径
        Path tempFilePath = Paths.get(targetPath, "temp_" + uniqueFilename);
        Path encryptedFilePath = Paths.get(targetPath, uniqueFilename);
        
        try {
            // 先保存原始文件到临时位置
            Files.copy(file.getInputStream(), tempFilePath, StandardCopyOption.REPLACE_EXISTING);
            
            // 对文件进行加密
            AESUtil.encryptFile(tempFilePath.toFile(), encryptedFilePath.toFile(), encryptionKey);
            
            // 删除临时文件
            Files.deleteIfExists(tempFilePath);
        } catch (Exception e) {
            // 出现异常时清理文件
            Files.deleteIfExists(tempFilePath);
            Files.deleteIfExists(encryptedFilePath);
            throw new RuntimeException(e);
        }

        // 验证加密文件是否真的保存成功
        if (!Files.exists(encryptedFilePath)) {
            throw new IOException("加密文件保存失败: " + encryptedFilePath.toString());
        }

        // 返回相对路径
        if (subDirectory != null && !subDirectory.isEmpty()) {
            return "/uploads/" + subDirectory + "/" + uniqueFilename;
        } else {
            return "/uploads/" + uniqueFilename;
        }
    }
    
    /**
     * 为课程阶段封面上传文件
     * 
     * @param file 要上传的文件
     * @param stageTitle 课程阶段标题
     * @return 文件的相对路径
     * @throws IOException 文件操作异常
     */
    public String uploadCourseStageCover(MultipartFile file, String stageTitle) throws IOException {
        if (file == null || file.isEmpty()) {
            return null;
        }
        return uploadFileToSubdirectory(file, "course_stage/" + sanitizePath(stageTitle));
    }
    
    /**
     * 为课程封面上传文件
     * 
     * @param file 要上传的文件
     * @param stageTitle 课程阶段标题
     * @param courseTitle 课程标题
     * @return 文件的相对路径
     * @throws IOException 文件操作异常
     */
    public String uploadCourseCover(MultipartFile file, String stageTitle, String courseTitle) throws IOException {
        if (file == null || file.isEmpty()) {
            return null;
        }
        return uploadFileToSubdirectory(file, 
            "course_stage/" + sanitizePath(stageTitle) + "/course/" + sanitizePath(courseTitle));
    }
    
    /**
     * 为课程内容封面上传文件
     * 
     * @param file 要上传的文件
     * @param stageTitle 课程阶段标题
     * @param courseTitle 课程标题
     * @param contentTitle 课程内容标题
     * @return 文件的相对路径
     * @throws IOException 文件操作异常
     */
    public String uploadCourseContentCover(MultipartFile file, String stageTitle, String courseTitle, String contentTitle) throws IOException {
        if (file == null || file.isEmpty()) {
            return null;
        }
        return uploadFileToSubdirectory(file, 
            "course_stage/" + sanitizePath(stageTitle) + "/course/" + sanitizePath(courseTitle) + "/course_content/" + sanitizePath(contentTitle));
    }
    
    /**
     * 为用户头像上传文件
     * 
     * @param file 要上传的文件
     * @return 文件的相对路径
     * @throws IOException 文件操作异常
     */
    public String uploadAvatar(MultipartFile file) throws IOException {
        if (file == null || file.isEmpty()) {
            return null;
        }
        return uploadFileToSubdirectory(file, "avatar");
    }
    
    /**
     * 为App APK文件上传
     * 
     * @param file 要上传的APK文件
     * @return 文件的相对路径
     * @throws IOException 文件操作异常
     */
    public String uploadAppFile(MultipartFile file) throws IOException {
        if (file == null || file.isEmpty()) {
            return null;
        }
        return uploadFileToSubdirectory(file, "app");
    }
    
    /**
     * 清理路径字符串，移除非法字符
     * 
     * @param path 路径字符串
     * @return 清理后的路径字符串
     */
    public String sanitizePath(String path) {
        if (path == null) {
            return "unknown";
        }
        // 将非法字符替换为下划线
        return path.replaceAll("[<>:\"/\\\\|?*]", "_");
    }
    
    /**
     * 删除文件
     *
     * @param filePath 文件的相对路径
     * @return 是否删除成功
     */
    public boolean deleteFile(String filePath) {
        if (filePath == null || filePath.isEmpty()) {
            return false;
        }
        
        try {
            // 从路径中提取文件名
            String fileName = filePath.substring(filePath.lastIndexOf('/') + 1);
            
            // 构建文件路径
            Path fileAbsolutePath = Paths.get(uploadPath, fileName);
            
            // 删除文件
            if (Files.exists(fileAbsolutePath)) {
                Files.delete(fileAbsolutePath);
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return false;
    }
    
    /**
     * 上传并裁剪图片文件
     *
     * @param file 要上传的文件
     * @param subDirectory 子目录名称
     * @param width 裁剪宽度
     * @param height 裁剪高度
     * @return 文件的相对路径
     * @throws IOException 文件操作异常
     */
    public String uploadAndCropImage(MultipartFile file, String subDirectory, int width, int height) throws IOException {
        if (file == null || file.isEmpty()) {
            return null;
        }

        // 确保上传目录存在
        String targetPath = uploadPath;
        if (subDirectory != null && !subDirectory.isEmpty()) {
            targetPath = Paths.get(uploadPath, subDirectory).toString();
        }
        
        File uploadDir = new File(targetPath);
        if (!uploadDir.exists()) {
            uploadDir.mkdirs();
        }

        // 生成唯一文件名
        String originalFilename = file.getOriginalFilename();
        String fileExtension = "";
        if (originalFilename != null && originalFilename.contains(".")) {
            fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
        }
        String uniqueFilename = UUID.randomUUID().toString() + fileExtension;

        // 构建文件路径
        Path filePath = Paths.get(targetPath, uniqueFilename);
        
        try {
            // 使用Thumbnailator进行图片裁剪并保存
            Thumbnails.of(file.getInputStream())
                    .size(width, height)
                    .crop(Positions.CENTER)
                    .toFile(filePath.toFile());
        } catch (IOException e) {
            throw new RuntimeException("图片裁剪失败: " + e.getMessage(), e);
        }

        // 验证文件是否真的保存成功
        if (!Files.exists(filePath)) {
            throw new IOException("文件保存失败: " + filePath.toString());
        }

        // 返回相对路径
        if (subDirectory != null && !subDirectory.isEmpty()) {
            return "/uploads/" + subDirectory + "/" + uniqueFilename;
        } else {
            return "/uploads/" + uniqueFilename;
        }
    }
    
    /**
     * 为用户头像上传并裁剪文件
     *
     * @param file 要上传的文件
     * @param width 裁剪宽度
     * @param height 裁剪高度
     * @return 文件的相对路径
     * @throws IOException 文件操作异常
     */
    public String uploadAndCropAvatar(MultipartFile file, int width, int height) throws IOException {
        if (file == null || file.isEmpty()) {
            return null;
        }
        return uploadAndCropImage(file, "avatar", width, height);
    }
    
    /**
     * 为课程阶段封面上传并裁剪文件
     *
     * @param file 要上传的文件
     * @param stageTitle 课程阶段标题
     * @param width 裁剪宽度
     * @param height 裁剪高度
     * @return 文件的相对路径
     * @throws IOException 文件操作异常
     */
    public String uploadAndCropCourseStageCover(MultipartFile file, String stageTitle, int width, int height) throws IOException {
        if (file == null || file.isEmpty()) {
            return null;
        }
        return uploadAndCropImage(file, "course_stage/" + sanitizePath(stageTitle), width, height);
    }
    
    /**
     * 为课程封面上传并裁剪文件
     *
     * @param file 要上传的文件
     * @param stageTitle 课程阶段标题
     * @param courseTitle 课程标题
     * @param width 裁剪宽度
     * @param height 裁剪高度
     * @return 文件的相对路径
     * @throws IOException 文件操作异常
     */
    public String uploadAndCropCourseCover(MultipartFile file, String stageTitle, String courseTitle, int width, int height) throws IOException {
        if (file == null || file.isEmpty()) {
            return null;
        }
        return uploadAndCropImage(file, 
            "course_stage/" + sanitizePath(stageTitle) + "/course/" + sanitizePath(courseTitle), 
            width, height);
    }
    
    /**
     * 为课程内容封面上传并裁剪文件
     *
     * @param file 要上传的文件
     * @param stageTitle 课程阶段标题
     * @param courseTitle 课程标题
     * @param contentTitle 课程内容标题
     * @param width 裁剪宽度
     * @param height 裁剪高度
     * @return 文件的相对路径
     * @throws IOException 文件操作异常
     */
    public String uploadAndCropCourseContentCover(MultipartFile file, String stageTitle, String courseTitle, String contentTitle, int width, int height) throws IOException {
        if (file == null || file.isEmpty()) {
            return null;
        }
        return uploadAndCropImage(file, 
            "course_stage/" + sanitizePath(stageTitle) + "/course/" + sanitizePath(courseTitle) + "/course_content/" + sanitizePath(contentTitle),
            width, height);
    }
}